-
Notifications
You must be signed in to change notification settings - Fork 30
fix(serializer): properly deserialize Interrupt objects to prevent At… #119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
96eb1f0 to
fd4be88
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes issue #113 where Interrupt objects were not properly deserialized by the Redis checkpoint serializer, causing AttributeError when LangGraph attempted to access Interrupt attributes after resuming from a checkpoint.
Key Changes:
- Added Interrupt object detection and reconstruction logic in
_revive_if_needed()method - Interrupt objects are now identified by their serialized form (dict with
value,resumable,ns, andwhenkeys) - Comprehensive test suite added with unit tests for serialization roundtrip, pending_sends scenarios, and full workflow integration
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
langgraph/checkpoint/redis/jsonplus_redis.py |
Enhanced _revive_if_needed() to detect and reconstruct Interrupt objects from their serialized dictionary form |
tests/test_issue_113_interrupt_serialization.py |
Added comprehensive regression tests covering direct serialization, pending_sends structure, and full workflow scenarios |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| return Interrupt( | ||
| value=obj["value"], | ||
| resumable=obj.get("resumable", False), |
Copilot
AI
Nov 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Inconsistent field access: The code checks that "resumable" in obj in the detection condition (line 95), guaranteeing the field exists, but then uses obj.get("resumable", False) with a default value. This is inconsistent - if the field is guaranteed to exist by the condition, use obj["resumable"] for consistency with the value field access on line 105. Alternatively, if defaults are intentional for robustness, apply the same pattern to all fields consistently.
| resumable=obj.get("resumable", False), | |
| resumable=obj["resumable"], |
…tributeError (#113) Fixes #113 When Interrupt objects are serialized with orjson, they become plain dictionaries with 'value', 'resumable', 'ns', and 'when' keys. Previously, these were not being reconstructed back to Interrupt objects during deserialization, causing AttributeError when LangGraph tried to access Interrupt attributes. Added logic to _revive_if_needed() to detect serialized Interrupt objects (dicts with exactly 4 keys: value, resumable, ns, when) and reconstruct them as Interrupt objects with proper recursive handling of nested objects. The fix handles: - Direct Interrupt object serialization/deserialization - Interrupts nested in data structures (lists, dicts) - Interrupts in pending_sends during checkpoint resume operations - Nested LangChain objects within Interrupt.value field Tests added: - test_interrupt_serialization_roundtrip: Unit test for basic serialization - test_interrupt_in_pending_sends: Test for Interrupts in pending_sends structure - test_interrupt_resume_workflow: Integration test reproducing the issue scenario
fd4be88 to
c3ce721
Compare
…tributeError (#113)
Fixes #113
When Interrupt objects are serialized with orjson, they become plain dictionaries with 'value' and 'id' keys. Previously, these were not being reconstructed back to Interrupt objects during deserialization, causing AttributeError when LangGraph tried to access the .id attribute.
Added logic to _revive_if_needed() to detect serialized Interrupt objects (dicts with exactly 'value' and 'id' keys where id is a string) and reconstruct them as Interrupt objects.
The fix handles:
Tests added: